﻿using SketchUpAPI.NET.Objects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SketchUpAPI.NET.Geometry
{
    /// <summary>
    /// 球
    /// </summary>
    public class Sphere : IGeometry
    {
        /// <summary>
        /// 球心
        /// </summary>
        public Point3D BasePoint { get; set; }

        /// <summary>
        /// 半径
        /// </summary>
        public double Radius { get; set; }

        /// <summary>
        /// U方向分段数
        /// </summary>
        /// <remarks>即一根经线的 半圆 要分成几段
        /// </remarks>
        public int USegment { get; set; } = 12;

        /// <summary>
        /// V方向分段数
        /// </summary>
        /// <remarks>即一根纬线的 圆 要分成几段</remarks>
        public int VSegment { get; set; } = 24;

        /// <summary>
        /// 球体北极方向
        /// </summary>
        public Vector3D North { get; set; } = Vector3D.UnitZ;

        /// <summary>
        /// X轴方向
        /// </summary>
        public Vector3D DirectorX { get; set; } = Vector3D.UnitX;

        /// <summary>
        /// 创建一个球
        /// </summary>
        /// <param name="center">球心</param>
        /// <param name="radius">半径</param>
        public Sphere(Point3D center, double radius)
        {
            BasePoint = center;
            Radius = radius;
        }

        public GeometryInput ToGeometry()
        {
            /* 创建球体
             * 1、根据经线分段数，创建所有的纬线
             * 2、相邻的两个纬线可以创建多个面
             * 3、创建南北极的三角面
             */

            GeometryInput gi = new GeometryInput();

            List<(Point3D Center, Point3D XPoint)> wefts = GetWefts();

            // 添加北极的三角面
            int northIndex = gi.AddVertex(BasePoint + North * Radius);
            var firstWeft = wefts.First();
            var firstIndex = gi.AddVertex(firstWeft.XPoint);
            gi.AddArc(firstIndex, firstIndex, firstWeft.Center, North, VSegment, out _);
            for (int i = 0; i < VSegment - 1; i++)
            {
                var pt1 = firstIndex + i;
                var pt2 = pt1 + 1;
                gi.AddFaceWithSmoothSoft(northIndex, pt1, pt2);
            }
            gi.AddFaceWithSmoothSoft(northIndex, firstIndex + VSegment - 1, firstIndex);

            // 添加中间纬线
            for (int i = 1; i < wefts.Count; i++)
            {
                var start = gi.AddVertex(wefts[i].XPoint);
                gi.AddArc(start, start, wefts[i].Center, North, VSegment, out _);

                for (int j = 0; j < VSegment - 1; j++)
                {
                    int pt1 = start + j;
                    int pt2 = pt1 + 1;
                    gi.AddFaceWithSmoothSoft(pt1, pt2, pt2 - VSegment, pt1 - VSegment);
                }

                gi.AddFaceWithSmoothSoft(start + VSegment - 1, start, start - VSegment, start - 1);
            }

            // 添加南极三角面
            int southIndex = gi.AddVertex(BasePoint - North * Radius);
            for (int i = 0; i < VSegment - 1; i++)
            {
                int pt1 = southIndex - i - 1;
                int pt2 = pt1 - 1;
                gi.AddFaceWithSmoothSoft(southIndex, pt1, pt2);
            }
            gi.AddFaceWithSmoothSoft(southIndex, southIndex - VSegment, southIndex - 1);

            return gi;
        }

        /// <summary>
        /// 计算所有纬线的X正方向象限点和半径
        /// </summary>
        /// <returns></returns>
        private List<(Point3D Center, Point3D XPoint)> GetWefts()
        {
            var result = new List<(Point3D, Point3D)>(USegment - 1);
            double degree = Math.PI / USegment;

            for (int i = 0; i < USegment - 1; i++)
            {
                double degreeToX = Math.PI / 2 - degree * (i + 1); // 与 X 轴的夹角
                double x = Math.Cos(degreeToX) * Radius;
                double y = Math.Sin(degreeToX) * Radius;

                Point3D center = BasePoint + North * y;
                Point3D xPoint = center + DirectorX * x;

                result.Add((center, xPoint));
            }

            return result;
        }
    }
}
